package plgnet

import (
	"dgo/goutils/gohttp"
	"dgo/goutils/utils"
	"gitee.com/ymofen/gobase/golog"
	"gitee.com/ymofen/supervalue"
	"golang.org/x/net/websocket"
	"net/http"
)

/*
推荐使用 v2023更新的版本

	2022-07-15 09:47:48
*/
type PlgHttpWsService struct {
	online int32
	PlgBase
	serviceUrl string

	// 订阅发送
	workers *utils.MultiGroupTask

	// 同步分发
	ws_ex *utils.SubscribeCenter

	monitor_recv *utils.MonitorSpeedSizeRec
	monitor_send *utils.MonitorSpeedSizeRec
}

/*
*

	{
	  "id":"ws-serv",
	  "type":"net.ws.service",
	  "conf":{
		"serviceurl":"/ws/service"
	   }
	}
*/
func (this *PlgHttpWsService) ReloadConf(conf *wrapper.SuperValue) error {
	if conf == nil {
		return nil
	}

	if this.ws_ex == nil {
		this.ws_ex = utils.NewSubscribeCenter()
	}

	if this.workers == nil {
		this.workers = utils.NewMultiGroupTask()
		this.workers.ConfigWorkType(2)
		this.workers.ConfigMinWork(1)
		this.workers.ConfigMaxWork(32)
		this.workers.Start()
	}

	if this.monitor_recv == nil {
		this.monitor_recv = utils.NewMonitorSpeedSizeRec()
		utils.Monitor.AddMonitor(this.monitor_recv)
	}

	if this.monitor_send == nil {
		this.monitor_send = utils.NewMonitorSpeedSizeRec()
		utils.Monitor.AddMonitor(this.monitor_send)
	}

	/**
	  兼容之前的
	*/
	conf.CheckExistsStrFunc("wsurl", func(strv string) {
		this.ConfigServiceURL(strv)
	})

	conf.CheckExistsStrFunc("serviceurl", func(strv string) {
		this.ConfigServiceURL(strv)
	})

	if len(this.serviceUrl) == 0 {
		golog.Warnf("没有启动Ws服务, 没有配置serviceurl参数")
	}

	return nil
}

func (this *PlgHttpWsService) ConfigServiceURL(strv string) {
	if this.serviceUrl != strv {
		if len(this.serviceUrl) > 0 {
			gohttp.UnHandle(this.serviceUrl)
		}
		this.serviceUrl = strv
		if len(this.serviceUrl) > 0 {
			wshd := websocket.Server{
				Handshake: func(config *websocket.Config, req *http.Request) (err error) {
					config.Origin, err = websocket.Origin(config, req)
					return nil // Origin 非法时不断开
					//if err == nil && config.Origin == nil {
					//	return fmt.Errorf("null origin")
					//}
					//return err
				},
				Handler: this.onHttpHandle,
			}
			//wshd := websocket.Handler(this.onHttpHandle)
			gohttp.Handle(this.serviceUrl, wshd)
		}
	}
}

func (this *PlgHttpWsService) Close() (err error) {
	utils.Monitor.RemoveMonitorRec(this.monitor_recv)
	utils.Monitor.RemoveMonitorRec(this.monitor_send)
	this.workers.Stop()
	this.PlgBase.Close()
	return
}

func (this *PlgHttpWsService) SendKVs(topic string, kv ...interface{}) error {
	if len(kv) == 1 {
		if json, ok := kv[0].(*wrapper.SuperValue); ok {
			json.SetKeyValue(WS_TOPIC_KEY, topic)
			this.ws_ex.DispatchData(topic, nil, json, nil)
		}
		return nil
	}

	json := wrapper.NewSVObject()
	json.SetKeyValue(WS_TOPIC_KEY, topic)
	json.SetKeyValues(kv...)
	this.ws_ex.DispatchData(topic, nil, json, nil)
	return nil
}

func (this *PlgHttpWsService) DispatchData(channelid string, sender interface{}, data interface{}, tag interface{}) (err error) {
	err = this.SendKVs(channelid, data)
	return err
}

func (this *PlgHttpWsService) SubscribeChannel(channelid string, id interface{}, cb utils.SubscribeCallback) {
	this.ws_ex.SubscribeChannel(channelid, id, cb)
}

func (this *PlgHttpWsService) UnsubscribeChannel(channelid string, id interface{}) bool {
	return this.ws_ex.UnsubscribeChannel(channelid, id)
}

func CreatePlgHttpWsServiceFunc(args ...interface{}) (rval interface{}, err error) {
	obj := &PlgHttpWsService{}

	if len(args) > 0 {
		if str, ok := args[0].(string); ok {
			obj.PlugId = str
		}
	}
	rval = obj
	return
}
